package automaton.rule;

import automaton.view.BooleanMatrix;

public class AutomatoCelularRegraGameLife extends AutomatoCelularRegra {

	public AutomatoCelularRegraGameLife(BooleanMatrix matrizTemporalAutomatos) {
		super(matrizTemporalAutomatos);
	}

	public void incrementarGeracao() {
		
		int lContaLinha, lContaColuna, lQtdVizinhos;
		BooleanMatrix lNovaMatriz = this.getMatrizTemporalAutomatos().clone(); 
		
		for(lContaLinha=0;lContaLinha<this.getMatrizTemporalAutomatos().getHeight();lContaLinha++) {
			for(lContaColuna=0;lContaColuna<this.getMatrizTemporalAutomatos().getWidth();lContaColuna++) {
				lQtdVizinhos = this.getQtdVizinhos(lContaLinha, lContaColuna, lNovaMatriz);
				
				// Solidao e super Populacao = Morte
				if((lQtdVizinhos < 2)||(lQtdVizinhos > 3)) {
					this.getMatrizTemporalAutomatos().setCell(lContaLinha, lContaColuna, false);
				} else if(lQtdVizinhos == 3) {
					this.getMatrizTemporalAutomatos().setCell(lContaLinha, lContaColuna, true);
				}
				
			}
		}
		

	}
	
	/**
	 * Retorna quantos vizinhos vivos o automato que est� na linha pLinha e coluna
	 * pColuna tem.
	 * @param pLinha linha do automato
	 * @param pColuna coluna do automato
	 * @return quantos vizinhos este automato tem
	 */
	private int getQtdVizinhos(int pLinha, int pColuna, BooleanMatrix pMatriz)
	{
		int lContaLinha, 
			lContaColuna,
			lMinLinha, 
			lMaxLinha, 
			lMinColuna, 
			lMaxColuna,
			lQtdVizinhos = 0;
		
		lMinLinha = pLinha-1;
		lMaxLinha = pLinha+1;
		lMinColuna = pColuna-1;
		lMaxColuna = pColuna+1;
		
		// Tratamento para out of bounds na primeira linha
		if(lMinLinha < 0) {
		  lMinLinha = 0;
		}
		
		// Tratamento ultima linha
		if(lMaxLinha >= pMatriz.getHeight())
		{
			lMaxLinha = pMatriz.getHeight()-1;
		}
		
		// Tratamento para out of bounds na primeira coluna
		if(lMinColuna<0) {
		  lMinColuna = 0;
		}
		
		// Tratamento ultima coluna
		if(lMaxColuna >= (pMatriz.getWidth()))
		{
			lMaxColuna = pMatriz.getWidth()-1;
		}
		
		for(lContaLinha = lMinLinha;lContaLinha <= lMaxLinha;lContaLinha++)
		{
			for(lContaColuna = lMinColuna; lContaColuna <= lMaxColuna; lContaColuna++)
			{
				try{
					if(((lContaLinha != pLinha)||(lContaColuna != pColuna))&&(pMatriz.getCell(lContaLinha,lContaColuna)))
					{
						lQtdVizinhos++;
					}
				} catch(Exception e) {
					System.out.println("linha:"+lContaLinha+" - col:"+lContaColuna);
				}
			}
		}
		
		return lQtdVizinhos;
	}

	public String toString() {
		return "Regra Game of Life";
	}

}
